<?php
/**
 * Created by 柚子i.
 * User: Emperor
 * Date: 2019/6/23
 * Time: 9:51
 */

namespace app\common\service\control;

use app\common\service\airquality\AqiService;
use app\common\service\BaseService;
use app\common\service\CommonService;
use app\common\service\companyIndustry\simulation\SimulationConcentrationService;
use app\common\service\companyIndustry\simulation\SimulationEfficiencyService;
use app\common\service\EmissionService;
use app\common\service\InletFlueGasService;
use think\Db;
use think\Exception;

ini_set('memory_limit', '2048M');

class ControlPlan extends BaseService
{
    private static $companyList = [];

    /**
     * ControlPlan constructor.
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function __construct()
    {
        parent::__construct();
        static::$companyList = db('basic_company')->where('delete_time', 'eq', 0)->select();

        static::$companyList = array_combine(array_column(static::$companyList, 'id'), array_column(static::$companyList, 'short_name'));
    }

    /**
     * Notes :获取提交的方案
     * @param $paramArr
     * @return array
     * @author lichao   2019/7/15
     */
    public function getControlPlanStatus($paramArr)
    {
        $plans      = $this->getPlanIdByPlanNumber($paramArr['plan_number']);
        $data       = array();
        $planStatus = array_column($plans, 'confirm_scheme');

        if (in_array(1, $planStatus)) {
            $data['confirmPlan']    = (int)substr($plans[array_search(1, $planStatus)]['name'], -1);
            $data['confirmExplain'] = $plans[array_search(1, $planStatus)]['explain'];
        } else {
            if ($planStatus[0] == 2) {
                $data['confirmPlan']    = 0;
                $data['confirmExplain'] = $plans[0]['explain'];
            } else {
                $data['confirmPlan']    = '';
                $data['confirmExplain'] = $plans[0]['explain'];
            }
        }

        return $data;
    }

    /**
     * Notes :获取方案总结
     * @param $paramArr
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @author lichao   2019/7/23
     */
    public function getConclusionData($paramArr)
    {
        $controlConfirm = new ControlPlanConfirm();
        // 获取确认的方案id
        $planId = $controlConfirm->getPlanIdByPlanNumber($paramArr['plan_number'], '', true);
        // 根据预案编号获取预案信息
        $planData = $this->getControlTime($paramArr['plan_number'], $paramArr['plan_type']);
        // 管控时段天日期
        $dateRange = getDateFromRange($planData['control_start_time'], $planData['control_end_time']);
        // 组合参数
        $param          = [
            "control_start_time" => $planData['control_start_time'],
            "control_end_time"   => $planData['control_end_time'],
            "publish_time"       => date("Y-m-d 00:00:00", strtotime($planData['control_start_time']) - 24 * 3600),
            "dayNum"             => count($dateRange),
            "plan_number"        => $paramArr['plan_number'],
            "plan_type"          => $paramArr['plan_type'],
            "plan_id"            => $planId,
        ];
        $conclusionData = array();
        // 获取脱硫运行浓度实现平均下降 TODO
        $conclusionData['TS_fall'] = 0;
        // 获取脱硝运行浓度实现平均下降 TODO
        $conclusionData['TN_fall'] = 0;
        // 获取预案减排量 TODO
        $conclusionData['plan_emission'] = 0;
        // 获取贡献度削减平均率 TODO
        $conclusionData['contribute_reduce'] = 0;
        // 获取运行效率实现平均提升 TODO
        $conclusionData['efficiency_promote'] = 0;
        // 获取预案减排成本 TODO
        $conclusionData['plan_cost'] = 0;
        // 获取企业响应率 TODO
        $conclusionData['company_response'] = 0;
        // 获取预案响应率 TODO
        $conclusionData['plan_response'] = 0;
        // 获取预案减排完成率 TODO
        $conclusionData['plan_emission_finish'] = 0;
        // 获取空气质量改善值
        $conclusionData['aqi_improve'] = $this->getAirQualityImprove($param);
        // 获取预案管控有效率 TODO
        $conclusionData['plan_control_valid'] = $this->controlEffectiveRate($param);

        return $conclusionData;
    }

    /**
     * Notes :获取预案管控有效率
     * @param $param
     * @return float|int
     * @author lichao   2019/7/29
     */
    public function controlEffectiveRate($param)
    {
        // 计算pm2.5 so2 no2 最大的值
        // 管控有效率 = 管控改善值 / 预案改善值
        //      管控改善值 = 实际值 - 预报值
        //      预案改善值 = 推演值 - 预报值

        $controlConfirm = new ControlPlanConfirm();
        // 获取管控时段实际值（天）
        $stationRealtimeData = $this->getStationRealtimeData($param['control_start_time'], $param['control_end_time'])[0];
        // 获取管控时段预报值（天）
        $stationForecastData = $controlConfirm->getForecastData($param['control_start_time'], $param['control_end_time'], $param['publish_time'], $param['dayNum']);
        // 获取管控时段推演值（天）
        $stationDeductionData = $controlConfirm->getDeductionData($param['control_start_time'], $param['control_end_time'], $param['publish_time'], $param['plan_number'], $param['plan_id'], $param['dayNum']);

        $pollutantArr     = ['pm25', 'so2', 'no2'];
        $effectiveRateAll = array();
        foreach ($pollutantArr as $item) {
            if ($stationDeductionData[$item] >= $stationForecastData[$item] ||
                $stationRealtimeData[$item] >= $stationForecastData[$item]) {
                continue;
            }
            $controlImprove          = $stationRealtimeData[$item] - $stationForecastData[$item];    // 管控改善值
            $deductionImprove        = $stationDeductionData[$item] - $stationForecastData[$item];    // 预案改善值
            $effectiveRateAll[$item] = $controlImprove / $deductionImprove;
        }

        if (!empty($effectiveRateAll)) {
            $maxEffectiveRate = max($effectiveRateAll);
            if ($maxEffectiveRate >= 1) {
                $effectiveRate = 100;
            } else {
                $effectiveRate = round($maxEffectiveRate * 100, 2);
            }
        } else {
            $effectiveRate = 0;
        }


        return $effectiveRate;
    }

    /**
     * Notes :获取全市空气质量改善值
     * @param $param
     * @return float
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @author lichao   2019/7/29
     */
    public function getAirQualityImprove($param)
    {
        // 获取全市管控中3天预报平均AQI
        $controlConfirm    = new ControlPlanConfirm();
        $cityFirstSevenAqi = $controlConfirm->getStationForecastAverageAqi($param);
        // 获取全市管控中3天实际平均AQI
        $cityControlAqi = $this->getCityControlAqi($param['control_start_time'], $param['control_end_time']);
        $cityImproveAqi = round($cityFirstSevenAqi - $cityControlAqi);

        return $cityImproveAqi;
    }

    /**
     * Notes :获取实测值减排前和管控中全市AQI
     * @param $controlStartTime
     * @param $controlEndTime
     * @return mixed
     * @author lichao   2019/7/3
     */
    public function getCityControlAqi($controlStartTime, $controlEndTime)
    {
        $aqi                 = new AqiService();
        $stationRealtimeData = $this->getStationRealtimeData($controlStartTime, $controlEndTime)[0];

        $aqiKeyArr       = [
            'pm10', 'pm25', 'so2', 'no2', 'co', 'o3', 'o3_8h'
        ];
        $realtime_cp_arr = array();
        foreach ($aqiKeyArr as $pollutantVal) {
            if ($pollutantVal == 'o3' || $pollutantVal == 'o3_8h') {
                // 实测数据
                $realPollutantVal = $stationRealtimeData[$pollutantVal];

                $realtime_cp_arr[$pollutantVal . '_average_max'] = $realPollutantVal;
            } else {
                // 实测数据
                $realPollutantVal = $stationRealtimeData[$pollutantVal];

                $realtime_cp_arr[$pollutantVal . '_average'] = $realPollutantVal;
            }
        }

        $cityAqi = $aqi->getAqi($realtime_cp_arr)['aqi'];

        return $cityAqi;
    }

    /**
     * Notes :第3步：预案推演
     * 根据预案编号及方案id获取站点6参预报值、推演值，计算推演改善值
     * @param $paramArr
     * @return array
     * @throws \Exception
     * @author lichao   2019/6/25
     */
    public function getStationTableData($paramArr)
    {
        try {
            $programmeNumber  = $paramArr['plan_number'];
            $planId           = $this->getPlanIdByPlanNumber($paramArr['plan_number'], $paramArr['plan_name']);
            $planData         = $this->getControlTime($paramArr['plan_number'], $paramArr['plan_type']);
            $publishTime      = date("Y-m-d 00:00:00", strtotime($planData['control_start_time']) - 24 * 3600);
            $controlStartTime = $planData['control_start_time'];
            $controlEndTime   = $planData['control_end_time'];
            $stationList      = $this->getStationList(53, 1);
            $dateRange        = getDateFromRange($controlStartTime, $controlEndTime);
            $dayNum           = count($dateRange);
            // 站点预报值
            $stationForecastData = $this->getStationForecastData($stationList, $dayNum, $publishTime, $controlStartTime, $controlEndTime);
            // 站点推演值
            $stationDeductionData = $this->getStationDeductionData($stationList, $dayNum, $programmeNumber, $planId, $publishTime, $controlStartTime, $controlEndTime);

            $aqi              = new AqiService();
            $newData          = array();
            $pollutantsKeyArr = [
                'pm10', 'pm25', 'so2', 'no2', 'co', 'o3', 'aqi'
            ];
            $aqiKeyArr        = [
                'pm10', 'pm25', 'so2', 'no2', 'co', 'o3', 'o3_8h'
            ];
            foreach ($stationList as $station => $stationName) {
                $forecast_cp_arr  = array();
                $deduction_cp_arr = array();
                foreach ($aqiKeyArr as $pollutantVal) {
                    $pollutantKey = $pollutantVal . "_" . $station;
                    if ($pollutantVal == 'o3' || $pollutantVal == 'o3_8h') {
                        if (isset($stationForecastData[$pollutantKey])) {
                            $forecast_cp_arr[$pollutantVal . '_average_max'] = $stationForecastData[$pollutantKey];
                        }
                        // if (isset($stationDeductionData[$pollutantKey])) {
                        $deduction_cp_arr[$pollutantVal . '_average_max'] = $stationDeductionData[$pollutantKey];
                        // }
                    } else {
                        $forecast_cp_arr[$pollutantVal . '_average']  = $stationForecastData[$pollutantKey];
                        $deduction_cp_arr[$pollutantVal . '_average'] = $stationDeductionData[$pollutantKey];
                    }
                }
                // 计算AQI
                $stationForecastAqi                      = $aqi->getAqi($forecast_cp_arr)['aqi'];
                $stationDeductionAqi                     = $aqi->getAqi($deduction_cp_arr)['aqi'];
                $stationForecastData['aqi_' . $station]  = $stationForecastAqi;
                $stationDeductionData['aqi_' . $station] = $stationDeductionAqi;
                foreach ($pollutantsKeyArr as $item) {
                    $pollutants   = $item == 'pm25' ? 'PM2_5' : strtoupper($item);
                    $pollutant    = $item == 'pm25' ? 'PM2.5' : strtoupper($item);
                    $pollutantKey = $item . "_" . $station;
                    if (isset($stationForecastData[$pollutantKey])) {
                        $forecastPollutantVal  = $stationForecastData[$pollutantKey];
                        $deductionPollutantVal = $stationDeductionData[$pollutantKey];
                        $improve               = $forecastPollutantVal - $deductionPollutantVal;
                        if (is_null($deductionPollutantVal)) {
                            $improve = '-';
                        }
                        $forecastValue  = $this->roundStationValue($forecastPollutantVal, $item);
                        $deductionValue = $this->roundStationValue($deductionPollutantVal, $item);
                        // 组合数组
                        $newData[$pollutants][$station]['station_id'] = $station;
                        $newData[$pollutants][$station]['site']       = $stationName;
                        $newData[$pollutants][$station]['pollutants'] = $pollutant;
                        $newData[$pollutants][$station]['forecast']   = $forecastValue;
                        $newData[$pollutants][$station]['deduction']  = is_null($deductionPollutantVal) ? '-' : $deductionValue;
                        $newData[$pollutants][$station]['improve']    = $improve != '-' ? round($improve, 1) : '-';
                    }
                }
            }

            // dump($newData);
            // die();

            // 计算平均改善值
            $new = array();
            if (!empty($newData)) {
                foreach ($newData as $i => $newDatum) {
                    $new[$i] = array_values($newDatum);
                    // $dataNum = count($newDatum);  // 计算站点数量
                    $dataSum = array();
                    foreach ($newDatum as $j => $item) {
                        if ($j != 0) {
                            array_push($dataSum, $item['improve']);
                            // $dataSum   = array_merge_recursive($dataSum, array_column($newDatum, 'improve'));
                        }
                    }
                    $new[$i . 'average'] = array_sum($dataSum) == 0 ? '-' : round(array_sum($dataSum) / 5, 1);
                }
            } else {
                return array([[], [], []]);
            }

            // dump($new);

            return $new;
        } catch (\Exception $e) {
            throw $e;
        }
    }

    /**
     * Notes :获取站点实际值
     * @param $controlStartTime
     * @param $controlEndTime
     * @return array|mixed
     * @author lichao   2019/7/1
     */
    public function getStationRealtimeData($controlStartTime, $controlEndTime)
    {
        // 获取站点实测值
        $stationRealtimeSql  = "SELECT * FROM `air_quality_station_aqi_realtime_day` WHERE `region_id` = 53 AND
 `publish_time` between ? AND ?";
        $stationRealtimeData = Db::query($stationRealtimeSql, array($controlStartTime, $controlEndTime));

        // 站点数据分组
        $realtimeData = array();
        foreach ($stationRealtimeData as $realtimeDatum) {
            $realtime = date("Y-m-d", strtotime($realtimeDatum['publish_time']));

            $realtimeData[$realtimeDatum['station_id']][$realtime] = $realtimeDatum;
        }

        $aqiKeyArr = [
            'pm10', 'pm25', 'so2', 'no2', 'co', 'o3', 'o3_8h'
        ];

        // 计算实际值平均值
        $stationRealtimeData = array();
        foreach ($realtimeData as $key => $realtimeDatum) {
            $realDayNum = count($realtimeDatum);
            foreach ($aqiKeyArr as $item) {
                $pollutantKey = $item == 'o3_8h' ? 'o3_8hour' : $item;
                $pollutants   = array_sum(array_column($realtimeDatum, $pollutantKey));

                $stationRealtimeData[$key][$item] = $pollutants / $realDayNum;
            }
        }

        return $stationRealtimeData;
    }

    /**
     * Notes :获取站点推演值
     * @param $stationList
     * @param $dayNum
     * @param $programmeNumber
     * @param $planId
     * @param $publishTime
     * @param $predictStartTime
     * @param $predictEndTime
     * @return mixed
     * @author lichao   2019/7/1
     */
    public function getStationDeductionData($stationList, $dayNum, $programmeNumber, $planId, $publishTime, $predictStartTime, $predictEndTime)
    {
        // 获取站点推演值
        $stationDeductionSql = "SELECT ";
        foreach ($stationList as $key => $item) {
            $stationDeductionSql .= "SUM(CASE WHEN station_id = " . $key . " THEN pm10 ELSE 0 END) / " . $dayNum .
                " as pm10_" . $key .
                ",SUM(CASE WHEN station_id = " . $key . " THEN pm25 ELSE 0 END) / " . $dayNum .
                " as pm25_" . $key .
                ",SUM(CASE WHEN station_id = " . $key . " THEN so2 ELSE 0 END) / " . $dayNum .
                " as so2_" . $key .
                ",SUM(CASE WHEN station_id = " . $key . " THEN no2 ELSE 0 END) / " . $dayNum .
                " as no2_" . $key .
                ",SUM(CASE WHEN station_id = " . $key . " THEN co ELSE 0 END) / " . $dayNum .
                " as co_" . $key .
                ",SUM(CASE WHEN station_id = " . $key . " THEN o3 ELSE 0 END) / " . $dayNum .
                " as o3_" . $key .
                ",SUM(CASE WHEN station_id = " . $key . " THEN o3_8hour ELSE 0 END) / " . $dayNum .
                " as o3_8h_" . $key . ",";
        }
        $stationDeductionSql = rtrim($stationDeductionSql, ',');

        $stationDeductionSql  .= " FROM `control_plan_from_bureau_station_details_day` WHERE `region_id` = 53
 AND `plan_number` = ? AND `tsinghua_plan_id` = ? AND `publish_time` = ? AND `predict_time` between ? AND ?";
        $stationDeductionData = Db::query($stationDeductionSql, array(
            $programmeNumber, $planId, $publishTime, $predictStartTime, $predictEndTime));

        return $stationDeductionData[0];
    }

    /**
     * Notes :获取站点预报数据
     * @param $stationList
     * @param $dayNum
     * @param $publishTime
     * @param $predictStartTime
     * @param $predictEndTime
     * @return mixed
     * @author lichao   2019/7/1
     */
    public function getStationForecastData($stationList, $dayNum, $publishTime, $predictStartTime, $predictEndTime)
    {
        // 获取站点预报值
        $stationForecastSql = "SELECT ";
        foreach ($stationList as $key => $item) {
            $stationForecastSql .= "SUM(CASE WHEN station_id = " . $key . " THEN pm10 ELSE 0 END) / " . $dayNum .
                " as pm10_" . $key .
                ",SUM(CASE WHEN station_id = " . $key . " THEN pm25 ELSE 0 END) / " . $dayNum .
                " as pm25_" . $key .
                ",SUM(CASE WHEN station_id = " . $key . " THEN so2 ELSE 0 END) / " . $dayNum .
                " as so2_" . $key .
                ",SUM(CASE WHEN station_id = " . $key . " THEN no2 ELSE 0 END) / " . $dayNum .
                " as no2_" . $key .
                ",SUM(CASE WHEN station_id = " . $key . " THEN co ELSE 0 END) / " . $dayNum .
                " as co_" . $key .
                ",SUM(CASE WHEN station_id = " . $key . " THEN o3 ELSE 0 END) / " . $dayNum
                . " as o3_" . $key .
                ",SUM(CASE WHEN station_id = " . $key . " THEN o3_8hour ELSE 0 END) / " . $dayNum .
                " as o3_8h_" . $key . ",";
        }
        $stationForecastSql  = rtrim($stationForecastSql, ',');
        $stationForecastSql  .= " FROM `air_quality_station_aqi_forecast_day` WHERE `region_id` = 53 AND 
`publish_time` = ? AND `predict_time` between ? AND ?";
        $stationForecastData = Db::query($stationForecastSql, array(
            $publishTime, $predictStartTime, $predictEndTime));

        return $stationForecastData[0];
    }

    /**
     * Notes :第3步：预案推演
     * 根据预案编号及方案id获取站点6参预报值、推演值数据
     * @param $paramArr
     * @return array
     * @throws \Exception
     * @author lichao   2019/6/25
     */
    public function getStationTrendChartData($paramArr)
    {
        try {
            $programmeNumber = $paramArr['plan_number'];
            $planId          = $this->getPlanIdByPlanNumber($paramArr['plan_number'], $paramArr['plan_name']);
            $planData        = $this->getControlTime($paramArr['plan_number'], $paramArr['plan_type']);
            $publishTime     = date("Y-m-d 00:00:00", strtotime($planData['control_start_time']) - 24 * 3600);
            // $planPublishTime = date("Y-m-d 19:00:00", strtotime($publishTime));
            $controlStartTime = $planData['control_start_time'];
            $controlEndTime   = $planData['control_end_time'];
            $stationId        = isset($paramArr['station_id']) ? $paramArr['station_id'] : 1;
            $pollutant        = isset($paramArr['pollutant']) ? $paramArr['pollutant'] : 'pm10';
            $dateRange        = getDateFromRange($controlStartTime, $controlEndTime, true);

            // 获取站点预报值
            $stationForecastSql  = "SELECT * FROM `air_quality_station_aqi_forecast_hour` WHERE `region_id` = 53 AND 
`station_id` = ? AND `publish_time` = ? AND `predict_time` between ? AND ?";
            $stationForecastData = Db::query($stationForecastSql, array(
                $stationId, $publishTime, $controlStartTime, $controlEndTime));
            if (!$stationForecastData) {
                throw new \Exception('获取站点预测值失败！');
            }
            $forecastPollutant = array_column($stationForecastData, $pollutant);

            // 获取站点推演值
            $stationDeductionSql  = "SELECT * FROM `control_plan_from_bureau_station_details_hour` WHERE
 `region_id` = 53 AND `station_id` = ? AND `plan_number` = ? AND `tsinghua_plan_id` = ? AND `publish_time` = ? AND
 `predict_time` between ? AND ?";
            $stationDeductionData = Db::query($stationDeductionSql, array(
                $stationId, $programmeNumber, $planId, $publishTime, $controlStartTime, $controlEndTime));
            // if (!$stationDeductionData) {
            //     throw new \Exception('获取站点推演值失败！');
            // }
            $deductionPollutant = array_column($stationDeductionData, $pollutant);

            // 组合数据
            $dateArr = handleStationTime($dateRange);
            $result  = [
                "date" => $dateArr,
                "data" => [
                    roundStationData($deductionPollutant, $pollutant),
                    roundStationData($forecastPollutant, $pollutant),
                ]
            ];

            return $result;
        } catch (\Exception $e) {
            throw $e;
        }
    }

    /**
     * Notes :获取站点列表
     * @param $regionId
     * @param $controlPoint
     * @return array
     * @author lichao   2019/7/4
     */
    public function getStationList($regionId, $controlPoint)
    {
        $stationList = [];
        $stationSql  = 'select * from basic_station where region_id = ? and control_point = ?';
        $station     = Db::query($stationSql, array($regionId, $controlPoint));

        foreach ($station as $value) {
            $stationList[$value['station_id']] = $value['name'];
        }

        return $stationList;
    }

    /**
     * Notes :站点数据四舍五入
     * @param $stationData
     * @param $param
     * @return float
     * @author lichao   2019/6/28
     */
    public function roundStationValue($stationData, $param)
    {
        if ($param == 'co') {
            $station = round($stationData, 1);
        } else {
            $station = round($stationData);
        }

        return $station;
    }

    /**
     * 获取溯源预报值
     * @param $planNumber string 预报编号
     * @param $beginDate string  管控开始时间
     * @param $endDate  string   管控结束时间
     * @param $isControl  bool   是否查询管控表中数据
     * @return mixed
     * @throws \MongoDB\Driver\Exception\Exception
     * @throws \Exception
     * @author  dutongtong   2019/6/26
     */
    public function getForecastDataByDate($planNumber, $beginDate, $endDate, $isControl = false)
    {
        //脱硫 脱销 模拟
        $inletFlueGasService = new InletFlueGasService();

        try {
            //企业运行效率列表
            $companyMonitorList = [];
            foreach ($inletFlueGasService->getAllCompanyDrainConcentrationEfficiency($planNumber) as $k => $v) {
                $companyMonitorList[$v['company_id']][$v['drain_name']] = $v;
            }

            // 定时任务生成 管控企业清单 的时候需要查询管控表中的数据
            if ($isControl) {
                $data = $this->getControlTablePollutantData($beginDate, $endDate);
            } else {
                $data = $this->getBeforeControlCompanyPollutent($beginDate, $endDate);
            }

            //脱硫 脱销 模拟
            $simulation = db('company_industry_monitor_simulation_day_avg')->select();

            $newSimulation = [];
            foreach ($simulation as $sk => $sv) {
                $newSimulation[$sv['company_id']][$sv['drain_name']] = $sv;
            }

            $new = [];
            foreach ($data as $key => $val) {
                if ($val['contribution_value'] == 0) continue;
                $new[$val['station_id']][$val['company_id']][$val['contribution_name']][] = $val;
            }

            $n[0] = $n[1] = $n[2] = $n[3] = $n[4] = $n[5] = [
                'O3'    => [],
                'PM10'  => [],
                'NO2'   => [],
                'PM2_5' => [],
                'SO2'   => [],
            ];
            sort($n);
            $pollutantArr = ['NO2' => 'nox', 'SO2' => 'so2', 'PM2.5' => 'tsp'];

            $emission      = new EmissionService();
            $commonService = new CommonService();
            $emissionList  = [];
            foreach ($emission->getAllCompanyDrainEmissionMinToHourAvg() as $v) {
                $emissionList[$v['company_id']][$v['drain_name']] = array_unique($v);
            }

            foreach ($new as $stationId => $stationData) {
                foreach ($stationData as $companyId => $companyData) {
                    foreach ($companyData as $polName => $polData) {
                        $concentration   = array_sum(array_column($polData, 'concentration'));
                        $contributionVal = (array_sum(array_column($polData, 'contribution_degree')) / $concentration);
                        if ($companyId == 1) {
                            $arr = [
                                'entriprise'              => static::$companyList[$companyId],
                                'company_id'              => $companyId,
                                'contribution'            => $commonService->contributionRound($contributionVal),
                                'pollutant_concentration' => $concentration,
                                'outlet'                  => '1#',//排口号
                                // 'emission'                => $emissionList[$companyId]['1#'][$pollutantArr[$polName] . '_emissions']
                                'emission'                => 0
                            ];
                            if ($polName == 'PM2.5') {
                                $arr['emission'] = round($emissionList[$companyId]['1#']['tsp_emissions']);
                            } else {
                                $arr['concentration'] = $companyMonitorList[$companyId]['1#']['concentration_' . $pollutantArr[$polName]];
                                $arr['efficiency']    = $companyMonitorList[$companyId]['1#']['efficiency_' . $pollutantArr[$polName]];
                            }
                            $n[$stationId][$polName == 'PM2.5' ? 'PM2_5' : $polName][] = $arr;
                        } else {
                            foreach ($newSimulation[$companyId] as $item => $v) {
                                $arr = [
                                    'company_id'              => $companyId,
                                    'entriprise'              => static::$companyList[$companyId],
                                    'contribution'            => $commonService->contributionRound(($contributionVal / count($newSimulation[$companyId]))),
                                    'outlet'                  => $item,//排口号
                                    'pollutant_concentration' => $concentration,
                                    'emission'                => 0
                                ];
                                if ($polName == 'PM2.5') {
                                    $arr['emission'] = round($emissionList[$companyId][$item]['tsp_emissions'] ?? 0, 2);
                                } else {
                                    $arr['concentration'] = $companyMonitorList[$companyId][$item]['concentration_' . $pollutantArr[$polName]];
                                    $arr['efficiency']    = $companyMonitorList[$companyId][$item]['efficiency_' . $pollutantArr[$polName]];
                                }
                                $n[$stationId][$polName == 'PM2.5' ? 'PM2_5' : $polName][] = $arr;
                            }
                        }
                    }
                }
            }
        } catch (\Exception $e) {
            throw $e;
        }
        return $n;
    }

    /**
     * Notes :获取方案id
     * @param $planNumber
     * @param $planName
     * @return mixed
     * @author lichao   2019/6/26
     */
    public function getPlanIdByPlanNumber($planNumber, $planName = '')
    {
        $bureauPlanSql = "SELECT * FROM `control_plan_from_tsinghua_plan` WHERE `plan_number` = ?";
        if ($planName != '') {
            $bureauPlanSql  .= " AND `name` = ?";
            $bureauPlanData = Db::query($bureauPlanSql, array($planNumber, $planName));

            return $bureauPlanData[0]['bureau_plan_id'];
        } else {
            $bureauPlanData = Db::query($bureauPlanSql, array($planNumber));

            return $bureauPlanData;
        }
    }

    /**
     * Notes :获取预案管控时段
     * @param $planNumber
     * @param $planType
     * @return mixed
     * @author lichao   2019/6/26
     */
    public function getControlTime($planNumber, $planType)
    {
        $controlPlanSql  = "SELECT * FROM `control_plan_name` WHERE `plan_number` = ?
 AND `plan_type` = ?";
        $controlPlanData = Db::query($controlPlanSql, array($planNumber, $planType));

        return $controlPlanData[0];
    }

    /**
     * 第一步 - 工况分析 运行浓度 | 运行效率 接口
     * @param string $planNumber
     * @param int $isConcentration 0 - 运行浓度, 1 - 运行效率
     * @return array|int
     * @throws \MongoDB\Driver\Exception\Exception
     * @throws \Exception
     * @author  dutongtong   2019/6/27
     */
    public function getIndustryMonitorLastWeekRecord(string $planNumber, int $isConcentration)
    {
        $field       = $isConcentration ? 'operating_efficiency' : 'operation_concentration';
        $sql         = <<<SQL
                SELECT
                    bc.id,bc.industry_id,bi.name
                FROM
                    basic_company bc
                left join
                basic_industry bi
                on bc.industry_id = bi.id
                WHERE
                    bc.delete_time = 0
                AND 
                    bc.id < 61
SQL;
        $companyList = db::query($sql);

        $data = [];

        $inletFlueGasService = new InletFlueGasService();
        try {
            if ($isConcentration) {
                $companyMonitorList = $inletFlueGasService->getCompanyOperatingEfficiency($planNumber);
                $companyMonitorList = array_column($companyMonitorList, null, 'company_id');

                //行业运行效率列表
                $industryMonitorList = $inletFlueGasService->getIndustryOperatingEfficiencyAll($planNumber);
                $industryMonitorList = array_column($industryMonitorList, null, 'industry_id');
            } else {
                $companyMonitorList = $inletFlueGasService->getCompanyOperationConcentration($planNumber);
                $companyMonitorList = array_column($companyMonitorList, null, 'company_id');

                //行业运行浓度列表
                $industryMonitorList = $inletFlueGasService->getIndustryOperationConcentrationAll($planNumber);
                $industryMonitorList = array_column($industryMonitorList, null, 'industry_id');
            }
            foreach ($companyList as $key => $val) {
                $data[$val['industry_id']][$val['id']][$field . '_nox'] = $isConcentration ?
                    $companyMonitorList[$val['id']]['no2_efficiency'] :
                    $companyMonitorList[$val['id']]['no2_concentration'];

                $data[$val['industry_id']][$val['id']][$field . '_so2'] = $isConcentration ?
                    $companyMonitorList[$val['id']]['so2_efficiency'] :
                    $companyMonitorList[$val['id']]['so2_concentration'];

                $data[$val['industry_id']][$val['id']]['name'] = $val['name'];
            }

            $n = [
                "NOX" => [
                    1 => [
                        'data' => [
                            []
                        ],
                        'date' => [],
                        'info' => []
                    ],
                    2 => [
                        'data' => [
                            []
                        ],
                        'date' => [],
                        'info' => []
                    ],
                    3 => [
                        'data' => [
                            []
                        ],
                        'date' => [],
                        'info' => []
                    ],
                    4 => [
                        'data' => [
                            []
                        ],
                        'date' => [],
                        'info' => []
                    ]
                ],
                "SO2" => [
                    1 => [
                        'data' => [
                            []
                        ],
                        'date' => [],
                        'info' => []
                    ],
                    2 => [
                        'data' => [
                            []
                        ],
                        'date' => [],
                        'info' => []
                    ],
                    3 => [
                        'data' => [
                            []
                        ],
                        'date' => [],
                        'info' => []
                    ],
                    4 => [
                        'data' => [
                            []
                        ],
                        'date' => [],
                        'info' => []
                    ]
                ],
            ];

            //浓度超标 标准值
            $concentrationCriterion = [
                1 => [
                    'SO2' => 35,
                    'NOX' => 50
                ],
                2 => [
                    'SO2' => 30,
                    'NOX' => 150
                ],
                3 => [
                    'SO2' => 180,
                    'NOX' => 300
                ],
                4 => [
                    'SO2' => 200,
                    'NOX' => 400
                ]
            ];

            foreach ($data as $industryId => $industryData) {
                foreach ($industryData as $companyId => $companyData) {
                    if (!isset(static::$companyList[$companyId])) {
                        unset($industryData[$companyId]);
                        continue;
                    }
                    //运行效率
                    if ($isConcentration) {
                        //当前行业运行效率
                        $industryNo2Avg = $industryMonitorList[$industryId]['operating_efficiency_nox'];
                        $industrySo2Avg = $industryMonitorList[$industryId]['operating_efficiency_so2'];
                        //当前企业运行效率低于行业效率
                        if ($companyData[$field . '_nox'] < $industryNo2Avg) {
                            $n['NOX'][$industryId]['date'][]    = static::$companyList[$companyId];
                            $n['NOX'][$industryId]['data'][0][] = round($companyData[$field . '_nox'] * 100, 2);
                            $n['NOX'][$industryId]['info'][]    = $companyId;
                        }
                        if ($companyData[$field . '_so2'] < $industrySo2Avg) {
                            $n['SO2'][$industryId]['date'][]    = static::$companyList[$companyId];
                            $n['SO2'][$industryId]['data'][0][] = round($companyData[$field . '_so2'] * 100, 2);
                            $n['SO2'][$industryId]['info'][]    = $companyId;
                        }
                    } else {
                        //运行浓度
                        if ($concentrationCriterion[$industryId]['SO2'] < $companyData[$field . '_so2']) {
                            $n['SO2'][$industryId]['date'][]    = static::$companyList[$companyId];
                            $n['SO2'][$industryId]['data'][0][] = $companyData[$field . 'so2'];
                            $n['SO2'][$industryId]['info'][]    = $companyId;
                        }
                        if ($concentrationCriterion[$industryId]['NOX'] < $companyData[$field . '_nox']) {
                            $n['NOX'][$industryId]['date'][]    = static::$companyList[$companyId];
                            $n['NOX'][$industryId]['data'][0][] = $companyData[$field . '_nox'];
                            $n['NOX'][$industryId]['info'][]    = $companyId;
                        }
                    }
                }
                $n['SO2']['hangye']['date'][]    = array_values($industryData)[0]['name'];
                $n['SO2']['hangye']['data'][0][] = round($industryMonitorList[$industryId][$field . '_so2'] * ($isConcentration ? 100 : 1), 2);

                $n['NOX']['hangye']['date'][]    = array_values($industryData)[0]['name'];
                $n['NOX']['hangye']['data'][0][] = round($industryMonitorList[$industryId][$field . '_nox'] * ($isConcentration ? 100 : 1), 2);
            }
        } catch (\Exception $e) {
            throw $e;
        }
        return $n;
    }

    /**
     * @param $planNumber
     * @param $planId
     * @param int $stationId 站点ID
     * @param int $companyId 公司ID
     * @param string $contribution 污染物名称
     * @param string $controlStartTime 管控开始时间
     * @param string $controlEndTime 管控结束时间
     * @return array
     * @throws Exception
     * @throws \MongoDB\Driver\Exception\Exception
     */
    public function getCompanyPollutent($stationId, $companyId, $planNumber, $planId, $contribution, $controlStartTime, $controlEndTime)
    {
        $data[] = $this->getControlCompanyPollutent(
            $controlStartTime,
            $controlEndTime,
            $planId,
            $planNumber,
            $stationId,
            $companyId,
            $contribution
        );

        $result          = [];
        $result['after'] = [];

        $commonService = new CommonService();
        if (!empty($data[0])) {
            // $avg = (array_sum(array_column($data[0], 'contribution_degree'))) / (count($data[0]));
            $contributionDegreeSum = array_sum(array_column($data[0], 'contribution_degree'));
            $concentrationSum      = array_sum(array_column($data[0], 'concentration'));
            $avg                   = $commonService->contributionRound($contributionDegreeSum / $concentrationSum);

            $data[0]                   = array_column($data[0], null, 'predict_time');
            $controlStartTime          = date('Y-m-d 00:00:00', strtotime($controlStartTime));
            $to                        = date('Y-m-d 00:00:00', strtotime('+1day', strtotime($controlStartTime)));
            $controlEndTime            = date('Y-m-d 00:00:00', strtotime($controlEndTime));
            $result['after']['date']   = [$controlStartTime, $to, $controlEndTime];
            $result['after']['data'][] = [
                $commonService->contributionRound($data[0][$controlStartTime]['contribution_value']) ?? 0,
                $commonService->contributionRound($data[0][$to]['contribution_value']) ?? 0,
                $commonService->contributionRound($data[0][$controlEndTime]['contribution_value']) ?? 0
            ];

            $result['after']['data'][] = [$avg, $avg, $avg];
        } else {
            $to                        = date('Y-m-d 00:00:00', strtotime('+1day', strtotime($controlStartTime)));
            $result['after']['date']   = [$controlStartTime, $to, $controlEndTime];
            $result['after']['data'][] = [0, 0, 0];
            $result['after']['data'][] = [0, 0, 0];
        }

        $data[] = $this->getBeforeControlCompanyPollutent(
            $controlStartTime,
            $controlEndTime,
            $stationId,
            $companyId,
            $contribution
        );

        $result['before'] = [];

        $contributionDegreeSum = array_sum(array_column($data[1], 'contribution_degree'));
        $concentrationSum      = array_sum(array_column($data[1], 'concentration'));
        $avg                   = round($commonService->contributionRound($contributionDegreeSum / $concentrationSum), 3);

        $data[1]                    = array_combine(array_column($data[1], 'predict_time'), array_values($data[1]));
        $controlStartTime           = date('Y-m-d 00:00:00', strtotime($controlStartTime));
        $controlEndTime             = date('Y-m-d 00:00:00', strtotime($controlEndTime));
        $to                         = date('Y-m-d 00:00:00', strtotime('+1day', strtotime($controlStartTime)));
        $result['before']['date']   = [$controlStartTime, $to, $controlEndTime];
        $result['before']['data'][] = [
            $commonService->contributionRound($data[1][$controlStartTime]['contribution_value']) ?? 0,
            $commonService->contributionRound($data[1][$to]['contribution_value']) ?? 0,
            $commonService->contributionRound($data[1][$controlEndTime]['contribution_value']) ?? 0
        ];

        $result['before']['data'][] = [$avg, $avg, $avg];

        return $result;
    }

    /**
     * 获取减排前贡献度
     * @param string $beginDate 管控开始时间
     * @param string $endDate 管控结束时间
     * @param int $stationId 站点ID
     * @param int $companyId 公司ID
     * @param string $contribution 污染物名称
     * @return mixed
     * @throws Exception
     * @throws \MongoDB\Driver\Exception\Exception
     */
    public function getBeforeControlCompanyPollutent($beginDate, $endDate, $stationId = 0, $companyId = 0, $contribution = '')
    {
        $document = [
            'aggregate'    => 'air_quality_pollutant_company_forecast_day',
            'pipeline'     => [
                [
                    '$project' => ['_id' => 0],
                ],
                [
                    '$match' => [
                        'publish_time' => date('Y-m-d 00:00:00', strtotime('-1day', strtotime($beginDate))),
                        'predict_time' => [
                            '$gte' => date('Y-m-d 00:00:00', strtotime($beginDate)),
                            '$lte' => date('Y-m-d 00:00:00', strtotime($endDate)),
                        ]
                    ]
                ]
            ],
            'allowDiskUse' => true,
        ];

        if ($contribution) {
            $document['pipeline'][1]['$match']['contribution_name'] = $contribution;
        }
        if ($companyId) {
            $document['pipeline'][1]['$match']['company_id'] = (int)$companyId;
        }
        if ($stationId) {
            $document['pipeline'][1]['$match']['station_id'] = (int)$stationId;
        }

        $mongo = new \MongoDB\Driver\Manager(
            "mongodb://root:Ws4815115!@dds-bp1babc036f87d64-pub.mongodb.rds.aliyuncs.com:3717"
        );

        $command = new \MongoDB\Driver\Command($document);
        $rows    = $mongo->executeCommand('huanxin', $command)->toArray();
        $data    = json_decode(json_encode($rows[0], 320), true)['result'];

        if (empty($data)) {
            throw new Exception('没有贡献度数据');
        }


        return $data;
    }

    /**
     * 获取减排中贡献度
     * @param $controlStartTime string 管控开始时间
     * @param $controlEndTime string 管控结束时间
     * @param $contribution string 污染物名称
     * @param $stationId int 站点ID
     * @param $companyId int 公司ID
     * @param $planId int 方案id
     * @param $planNumber string 预案编号
     * @return mixed
     * @throws Exception
     * @throws \MongoDB\Driver\Exception\Exception
     */
    public function getControlCompanyPollutent($controlStartTime, $controlEndTime, $planId = 1, $planNumber = '', $stationId = 0, $companyId = 0, $contribution = '')
    {
        $planList = [
            '方案1' => 1,
            '方案2' => 2,
            '方案3' => 3
        ];
        $document = [
            'aggregate'    => 'control_deduction_pollutant_day',
            'pipeline'     => [
                [
                    '$project' => [
                        '_id' => 0
                    ]
                ],
                [
                    '$match' => [
                        'plan_number'  => $planNumber,
                        'plan_id'      => (int)$planList[$planId],
                        'predict_time' => [
                            '$gte' => $controlStartTime,
                            '$lte' => $controlEndTime,
                        ],
                    ]
                ]
            ],
            'allowDiskUse' => true,
        ];

        if ($contribution) {
            $document['pipeline'][1]['$match']['contribution_name'] = $contribution;
        }
        if ($companyId) {
            $document['pipeline'][1]['$match']['company_id'] = (int)$companyId;
        }
        if ($stationId) {
            $document['pipeline'][1]['$match']['station_id'] = (int)$stationId;
        }

        $mongo = new \MongoDB\Driver\Manager(
            "mongodb://root:Ws4815115!@dds-bp1babc036f87d64-pub.mongodb.rds.aliyuncs.com:3717"
        );

        $command = new \MongoDB\Driver\Command($document);
        $rows    = $mongo->executeCommand('huanxin', $command)->toArray();
        $data    = json_decode(json_encode($rows[0], 320), true)['result'];

        return $data;
    }

    /**
     * 获取溯源5点预报数据 - 管控生成企业清单用
     * @param $beginDate
     * @param $endDate
     * @return mixed
     * @throws Exception
     * @throws \MongoDB\Driver\Exception\Exception
     * @author  dutongtong   2019/8/10
     */
    public function getControlTablePollutantData($beginDate, $endDate)
    {
        $document = [
            'aggregate'    => 'air_quality_pollutant_company_forecast_day_control',
            'pipeline'     => [
                [
                    '$project' => ['_id' => 0],
                ],
                [
                    '$match' => [
                        'publish_time' => date('Y-m-d', strtotime('-1day', strtotime($beginDate))) . ' 05:00:00',
                        'predict_time' => [
                            '$gte' => date('Y-m-d', strtotime($beginDate)) . ' 00:00:00',
                            '$lte' => date('Y-m-d', strtotime($endDate)) . ' 00:00:00',
                        ]
                    ]
                ]
            ],
            'allowDiskUse' => true,
        ];

        $mongo = new \MongoDB\Driver\Manager(
            "mongodb://root:Ws4815115!@dds-bp1babc036f87d64-pub.mongodb.rds.aliyuncs.com:3717"
        );

        $command = new \MongoDB\Driver\Command($document);
        $rows    = $mongo->executeCommand('huanxin', $command)->toArray();
        $data    = json_decode(json_encode($rows[0], 320), true)['result'];

        if (empty($data)) {
            throw new Exception('没有贡献度数据');
        }
        return $data;
    }
}
